package gui;

import java.io.File;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.concurrent.LinkedBlockingQueue;

import javax.swing.DefaultListModel;
import javax.swing.JFileChooser;

import chatsystemTDa2.*;
import model.RemoteUser;
import model.UserList;
import controller.ChatController;
import controller.Msg;
/**
 *  This is the part communicate directly to the chat controller
 *  link to ChatController
 *  link to DefaultListModel that is connected users list 
 *  link to LinkedBlockingQueue <Msg> that is the buffer of received messages
 */

public class ChatGUI extends Thread{
	private ChatController chatController;
	private ConnectWindow connectWindow;
	private ConversationWindow conversationWindow;
	private UserListWindow userlistWindow;
	
	private File selectedFile;
	
	JFileChooser fileDialog = null;
	//connected user list:
	private DefaultListModel userList;
	//list of actual conversation windows
	private ArrayList <ConversationWindow> listConversationWindow;
	//received message list
	private LinkedBlockingQueue <Msg> listMsgRcvd;
	//variable pour fermer le thread
	private boolean stopThread = false;

	public ChatGUI(ChatController chatController, DefaultListModel userList,LinkedBlockingQueue <Msg> listMsgRcvd){
		this.chatController = chatController;
		this.userList = userList;
		this.connectWindow = new ConnectWindow(this);
		this.listConversationWindow = new ArrayList <ConversationWindow> ();
		this.listMsgRcvd = listMsgRcvd;
		this.start();
	}
	
	/**
	 * open user list window when we connect
	 * @param userList a list of connected users
	 */
	public void setUserList(DefaultListModel userList){
		this.userlistWindow = new UserListWindow(userList, this);
	}
	
	/**
	 * open the conversation window
	 * @param remoteUser the one that own this conversation
	 * @return
	 */
	public ConversationWindow setConversation(RemoteUser remoteUser){
		this.conversationWindow = new ConversationWindow(remoteUser, this);
		return this.conversationWindow;
	}
	
	/**
	 * when we click on the connect button, chatGUI run this method
	 * @param username our user name
	 */
	public void connect(String username){
		chatController.process_connect(username);
	}
	
	/**
	 * when we click on disconnect button, chatGUI run this method
	 */
	public void disconnect(){
		chatController.process_disconnect();
	}
	
	
	/**
	 * when we click on send button, chatGUI run this method
	 * @param text
	 * @param remoteUser
	 */
	public void send(String text, RemoteUser remoteUser){
		chatController.process_send(text, remoteUser);
	}
	
	/**
	 * getter for connected user list
	 * @return the connected user list of chatGUI
	 */
	public DefaultListModel getUserList(){
		return userList;
	}
	
	/**
	 * When we open a conversation window, add this window to the listConverversation
	 * @param conversationWindow a conversation object that we want to add in list
	 */
	public void addListConversation (ConversationWindow conversationWindow){
		listConversationWindow.add(conversationWindow);
	}
	
	/**
	 * When we close a conversation window, remove this window from the listConverversation
	 * @param conversationWindow a conversation object that we want to remove from list
	 */
	public void removeElementListConversation (ConversationWindow conversationWindow){
		for (int i=0; i< listConversationWindow.size();i++){
			if (listConversationWindow.get(i) == conversationWindow){
				listConversationWindow.remove(i);
				break;
			}
		}
	}
	
	/**
	 * getter for the list of actual conversation windows
	 * @return
	 */
	public ArrayList <ConversationWindow> getListConversation(){
		return this.listConversationWindow;
	}
	
	
	/**
	 * update the conversation when receiving message. If the conversation of the sender was created, just add the msg to this conversaiton
	 * If it wasn't, create a new conversation and add this message in it 
	 * @param msg received message
	 * @param RUser the sender of this message
	 */
	public void updateConversation(String msg, RemoteUser RUser){
		int Update = 0;
		for (int i=0; i< listConversationWindow.size();i++){
			if (listConversationWindow.get(i).getRemoteUser() == RUser){
				listConversationWindow.get(i).updateConversation(msg, RUser.getUsername());
				Update = 1;
			}
		}
		
		if (Update == 0) {
			ConversationWindow newConversation = this.setConversation(RUser);
			this.addListConversation(newConversation);
			newConversation.updateConversation(msg, RUser.getUsername());
		}
	}
	
	/**
	 * create a conversation if it wasn't created or do nothing if it was
	 * @param RUser the one we want to talk with
	 */
	public void creerConversation(RemoteUser RUser){
		int Creation = 0;
		for (int i=0; i< listConversationWindow.size();i++){
			if (listConversationWindow.get(i).getRemoteUser() == RUser){
				Creation =1;
			}
		}
		
		if (Creation == 0) {
			ConversationWindow newConversation = this.setConversation(RUser);
			this.addListConversation(newConversation);
		}
	}
	
	/**
	 * when a remote user is disconnected, we have to close his conversation window
	 * @param ip IP address of the remote user that own this conversation
	 */
	public void closeConversation(InetAddress ip){
		for (int i=0; i< listConversationWindow.size();i++){
			if (listConversationWindow.get(i).getRemoteUser().getIP().equals(ip)){
				listConversationWindow.get(i).dispose();
				listConversationWindow.remove(i);
			}
		}
	}
	
	/**
	 * open a dialog to choose a file
	 */
	public void chooseFileDialog()
    {
        if (fileDialog == null) 
        {
            fileDialog = new JFileChooser();    
        }
        int returnVal = fileDialog.showDialog(conversationWindow, "Choose");
        if (returnVal == JFileChooser.APPROVE_OPTION)
        {
            this.setSelectedFile(fileDialog.getSelectedFile());
        } 
        fileDialog.setSelectedFile(null);
    }  
 
	public void setSelectedFile(File file){
		this.selectedFile = file;
	}
 
	public File getSelectedFile(){
		return this.selectedFile;
	}
    /*******************************/
	
	/**
	 * close thread	
	 */
	public void close(){
		this.stopThread = true;
	}
	
	/**
	 * action for chatGUI's thread
	 */
	public void run(){
		while (!stopThread){
			try {
				//if (listMsgRcvd != null){
					Msg m = listMsgRcvd.take();
					//if (this.userlistWindow.getUser(m.getIp()) != null){
						System.out.println("OK");
						this.updateConversation(((Send) m.getMsg()).getMessage(), this.userlistWindow.getUser(m.getIp()));	
					//}
					//else System.out.println(((Send) m.getMsg()).getMessage());
				//}
			} catch (InterruptedException e) {System.out.println("KO");}
		}
	}
	 
}
